// 自定义高性能的遍历方法
function forEach(arr, iterator) {
  let index = 0;
  const len = arr.length;

  while (index < len) {
    iterator(arr[index], index);
    index++;
  }

  return arr;
}

/**
 * 深拷贝
 * @param {Object} obj 要拷贝的对象
 * @param {Map} map 用于存储循环引用对象的地址
 */
function deepClone(obj, map = new WeakMap()) {
  if (typeof obj !== "object") {
    return obj;
  }

  if (map.get(obj)) {
    return map.get(obj);
  }

  const isArray =
    Array.isArray(obj) ||
    Object.prototype.toString.call(obj) === "[object Array]";

  let result = isArray ? [] : {};

  map.set(obj, result);

  const iteratorArr = isArray ? obj : Object.keys(obj);
  forEach(iteratorArr, (val, key) => {
    if (!isArray) {
      key = val;
    }
    result[key] = deepClone(obj[key], map);
  });

  return result;
}

const target = {
  field1: 1,
  field2: undefined,
  field3: "ConardLi",
  field4: {
    child: "child",
    child2: {
      child2: "child2",
    },
  },
  field5: [1, 2, 3, 4],
};

target.field6 = target;
console.log(target);
console.log(deepClone(target));




// ******简洁易懂版

function deepClone(source, hash = new WeakMap()) {
  // 处理null和基本数据类型
  if (source === null || typeof source !== 'object') {
    return source;
  }
  
  // 处理循环引用
  if (hash.has(source)) {
    return hash.get(source);
  }
  
  let clone;
  
  // 处理数组
  if (Array.isArray(source)) {
    clone = [];
    // 处理循环引用,因为储存的是地址，所以后面的遍历结果也会影响到hash
    // 如果遍历后再添加，就无法处理循环遍历问题了
    hash.set(source, clone);
    for (let i = 0; i < source.length; i++) {
      clone[i] = deepClone(source[i], hash);
    }
    return clone;
  }
  
  // 处理普通对象
  if (source instanceof Object) {
    clone = {};
    hash.set(source, clone);
    // 遍历对象的所有自有属性
    Reflect.ownKeys(source).forEach(key => {
      clone[key] = deepClone(source[key], hash);
    });
    return clone;
  }
  
  // 处理其他类型（如函数等）
  return source;
}